from rest_framework import serializers
from rest_framework.fields import URLField
from rest_framework.serializers import ModelSerializer
from apps.classes.models import Class
from apps.courses.models import Course
from apps.teachers.models import Teacher


class ClassModelSerializer(ModelSerializer):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 将需要返回描述信息的字段设置为只写必须字段(仅用作反序列化),在后续使用SerializerMethodField计算字段专门负责序列化返回
        self.fields['schooltime'].write_only = True
        self.fields['schooltime'].required = True
        self.fields['teach_method'].write_only = True
        self.fields['teach_method'].required = True
        self.fields['state'].write_only = True
        self.fields['state'].required = True

    # PrimaryKeyRelatedField 负责反序列化, 自定义字段负责序列化返回
    course_name = serializers.CharField(source='course.name', read_only=True)
    speaker_nickname = serializers.CharField(source='speaker.nickname', read_only=True)
    head_nickname = serializers.CharField(source='head.nickname', read_only=True)
    course = serializers.PrimaryKeyRelatedField(label='课程', queryset=Course.objects.all(), write_only=True)
    speaker = serializers.PrimaryKeyRelatedField(label='主讲老师', queryset=Teacher.objects.all(), write_only=True)
    head = serializers.PrimaryKeyRelatedField(label='班主任', queryset=Teacher.objects.all(), write_only=True)

    schooltime_desc = serializers.SerializerMethodField(source='schooltime', read_only=True)
    teach_method_desc = serializers.SerializerMethodField(source='teach_method', read_only=True)
    state_desc = serializers.SerializerMethodField(source='state', read_only=True)

    data_link = URLField(allow_null=True, allow_blank=True, label='班级信息备注', max_length=50, required=False)

    # 根据原始字段的数字解析出描述信息返回;方法名要求get_SerializerMethodField实例化的字段名(schooltime_desc)
    @staticmethod
    def get_schooltime_desc(obj):
        return dict(Class.SCHOOLTIME_CHOICES)[obj.schooltime]

    @staticmethod
    def get_teach_method_desc(obj):
        return dict(Class.TEACHMETHOD_CHOICES)[obj.teach_method]

    @staticmethod
    def get_state_desc(obj):
        return dict(Class.STATE_CHOICES)[obj.state]

    class Meta:
        model = Class
        fields = '__all__'

    @staticmethod
    def validate_stage_no(value):
        """班期必须以cls开头"""
        if not value.startswith('cls'):
            raise serializers.ValidationError('班期必须以cls开头, 例如cls20!')
        return value


# 继承ClassModelSerializer并修改更新逻辑: stage_no与course字段只接受原值或不传递(不可被修改)
class UpdateClassModelSerializer(ClassModelSerializer):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # stage_no与course字段非必传字段
        self.fields['stage_no'].required = False
        self.fields['course'].required = False

    def validate(self, attrs):
        # 更新才会有instance
        instance = getattr(self, 'instance', None)
        if instance:
            stage_no = attrs.get("stage_no", None)
            course = attrs.get("course", None)
            if (stage_no is not None) and stage_no != instance.stage_no:
                raise serializers.ValidationError('班期不允许更新!')
            if (course is not None) and course != instance.course:
                raise serializers.ValidationError('课程不允许更新!')
        return attrs




